]> dgit.raspbian.org Git - pcre2.git/commitdiff
Backport of pcre2-10.48-Check-JIT-mode-before-validation.patch
authorZoltan Herczeg <zherczeg7@gmail.com>
Sun, 9 Aug 2026 09:05:54 +0000 (11:05 +0200)
committerMatthew Vernon <matthew@debian.org>
Tue, 1 Sep 2026 10:43:48 +0000 (11:43 +0100)
Cherry-pick of f67db227af31bba7cdf2a7a00b97af91b588c2f5 and e2f100156b94cf85dce9046b47a3274590487de4

Fix pcre2_match to check for JIT support before JIT validation & execution (#926)

This fixes the issue that the JIT branch's UTF validation is not pinned to be identical to the interpreter's validation.

This was not robust, and lead to a bug, in the case where the JIT UTF validation is done, but because the relevant JIT mode was not compiled, it falls through to the interpreter and skips the interpreter's own UTF validation and setup.

Add a testcase for #926 (#940)

(cherry picked from commit ab7097fbde778e0e4d17752ba2a14a7430d35385)

src/pcre2_internal.h
src/pcre2_jit_match.c
src/pcre2_jit_misc.c
src/pcre2_match.c
testdata/testinput17
testdata/testoutput17

index a22e8b15193e1a5dab488afe5bcb536cdc50c625..3b570eab3a7be501a317602c05560faf5a66cfb7 100644 (file)
@@ -2175,6 +2175,7 @@ is available. */
 #define _pcre2_is_newline            PCRE2_SUFFIX(_pcre2_is_newline_)
 #define _pcre2_jit_free_rodata       PCRE2_SUFFIX(_pcre2_jit_free_rodata_)
 #define _pcre2_jit_free              PCRE2_SUFFIX(_pcre2_jit_free_)
+#define _pcre2_jit_check_exec        PCRE2_SUFFIX(_pcre2_jit_check_exec_)
 #define _pcre2_jit_get_size          PCRE2_SUFFIX(_pcre2_jit_get_size_)
 #define _pcre2_jit_get_target        PCRE2_SUFFIX(_pcre2_jit_get_target_)
 #define _pcre2_memctl_malloc         PCRE2_SUFFIX(_pcre2_memctl_malloc_)
@@ -2203,6 +2204,7 @@ extern BOOL         _pcre2_is_newline(PCRE2_SPTR, uint32_t, PCRE2_SPTR,
                       uint32_t *, BOOL);
 extern void         _pcre2_jit_free_rodata(void *, void *);
 extern void         _pcre2_jit_free(void *, pcre2_memctl *);
+extern BOOL         _pcre2_jit_check_exec(void *, uint32_t);
 extern size_t       _pcre2_jit_get_size(void *);
 const char *        _pcre2_jit_get_target(void);
 extern void *       _pcre2_memctl_malloc(size_t, pcre2_memctl *);
index 23a2d405f30da664080e9ea3a03256ebc1c93a20..6afc6d969b51339e8aeb5db5a2609e23e3d68469 100644 (file)
@@ -118,6 +118,7 @@ jit_arguments arguments;
 int rc;
 int index = 0;
 
+/* The same check is performed by jit_check_exec(). */
 if ((options & PCRE2_PARTIAL_HARD) != 0)
   index = 2;
 else if ((options & PCRE2_PARTIAL_SOFT) != 0)
index c3abc0b33bd4b2de29c4533581a2e37f5ed0526a..2045232602c373c8beb4a7331e60ef905428ff6d 100644 (file)
@@ -214,6 +214,32 @@ return sljit_get_platform_name();
 }
 
 
+/*************************************************
+*          Checks function compilation           *
+*************************************************/
+
+BOOL
+PRIV(jit_check_exec)(void *executable_jit, uint32_t options)
+{
+#ifndef SUPPORT_JIT
+(void)executable_jit;
+(void)options;
+return FALSE;
+#else  /* SUPPORT_JIT */
+/* The same check is performed at the beginning of pcre2_jit_match(). */
+executable_functions *functions = (executable_functions *)executable_jit;
+int index = 0;
+
+if ((options & PCRE2_PARTIAL_HARD) != 0)
+  index = 2;
+else if ((options & PCRE2_PARTIAL_SOFT) != 0)
+  index = 1;
+
+return functions->executable_funcs[index] != NULL;
+#endif
+}
+
+
 /*************************************************
 *              Get size of JIT code              *
 *************************************************/
index 34a92eaa36ed369a845c6a602c467e7e9f6864f3..faedff77ce23eeef3173a9dbb581883b926c437e 100644 (file)
@@ -6867,10 +6867,6 @@ PCRE2_SPTR req_cu_ptr;
 PCRE2_SPTR start_partial;
 PCRE2_SPTR match_partial;
 
-#ifdef SUPPORT_JIT
-BOOL use_jit;
-#endif
-
 /* This flag is needed even when Unicode is not supported for convenience
 (it is used by the IS_NEWLINE macro). */
 
@@ -6880,9 +6876,6 @@ BOOL utf = FALSE;
 BOOL ucp = FALSE;
 BOOL allow_invalid;
 uint32_t fragment_options = 0;
-#ifdef SUPPORT_JIT
-BOOL jit_checked_utf = FALSE;
-#endif
 #endif  /* SUPPORT_UNICODE */
 
 PCRE2_SIZE frame_size;
@@ -6943,15 +6936,6 @@ options |= (re->flags & FF) / ((FF & (~FF+1)) / (OO & (~OO+1)));
 #undef FF
 #undef OO
 
-/* If the pattern was successfully studied with JIT support, we will run the
-JIT executable instead of the rest of this function. Most options must be set
-at compile time for the JIT code to be usable. */
-
-#ifdef SUPPORT_JIT
-use_jit = (re->executable_jit != NULL &&
-          (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0);
-#endif
-
 /* Initialize UTF/UCP parameters. */
 
 #ifdef SUPPORT_UNICODE
@@ -6997,20 +6981,25 @@ match_data->startchar = 0;
 
 /* ============================= JIT matching ============================== */
 
-/* Prepare for JIT matching. Check a UTF string for validity unless no check is
-requested or invalid UTF can be handled. We check only the portion of the
-subject that might be be inspected during matching - from the offset minus the
-maximum lookbehind to the given length. This saves time when a small part of a
-large subject is being matched by the use of a starting offset. Note that the
-maximum lookbehind is a number of characters, not code units. */
+/* If the pattern was successfully studied with JIT support, we will run the
+JIT executable instead of the rest of this function. Most options must be set
+at compile time for the JIT code to be usable. */
 
 #ifdef SUPPORT_JIT
-if (use_jit)
+if (re->executable_jit != NULL &&
+    (options & ~PUBLIC_JIT_MATCH_OPTIONS) == 0 &&
+    PRIV(jit_check_exec)(re->executable_jit, options))
   {
+  /* Prepare for JIT matching. Check a UTF string for validity unless no check
+  is requested or invalid UTF can be handled. We check only the portion of the
+  subject that might be be inspected during matching - from the offset minus
+  the maximum lookbehind to the given length. This saves time when a small part
+  of a large subject is being matched by the use of a starting offset. Note that
+  the maximum lookbehind is a number of characters, not code units. */
+
 #ifdef SUPPORT_UNICODE
   if (utf && (options & PCRE2_NO_UTF_CHECK) == 0 && !allow_invalid)
     {
-
     /* For 8-bit and 16-bit UTF, check that the first code unit is a valid
     character start. */
 
@@ -7063,16 +7052,14 @@ if (use_jit)
       match_data->startchar += start_match - subject;
       return match_data->rc;
       }
-    jit_checked_utf = TRUE;
     }
 #endif  /* SUPPORT_UNICODE */
 
-  /* If JIT returns BADOPTION, which means that the selected complete or
-  partial matching mode was not compiled, fall through to the interpreter. */
-
   rc = pcre2_jit_match(code, subject, length, start_offset, options,
     match_data, mcontext);
-  if (rc != PCRE2_ERROR_JIT_BADOPTION)
+  /* JIT must be able to perform the match. */
+  PCRE2_ASSERT(rc != PCRE2_ERROR_JIT_BADOPTION);
+
     {
     match_data->subject_length = length;
     if (rc >= 0 && (options & PCRE2_COPY_MATCHED_SUBJECT) != 0)
@@ -7098,12 +7085,8 @@ this. */
 
 mb->check_subject = subject;
 
-/* If a UTF subject string was not checked for validity in the JIT code above,
-check it here, and handle support for invalid UTF strings. The check above
-happens only when invalid UTF is not supported and PCRE2_NO_CHECK_UTF is unset.
-If we get here in those circumstances, it means the subject string is valid,
-but for some reason JIT matching was not successful. There is no need to check
-the subject again.
+/* Check the validity of UTF subject strings. The check happens only when
+PCRE2_NO_CHECK_UTF is unset.
 
 We check only the portion of the subject that might be be inspected during
 matching - from the offset minus the maximum lookbehind to the given length.
@@ -7115,11 +7098,7 @@ Note also that support for invalid UTF forces a check, overriding the setting
 of PCRE2_NO_CHECK_UTF. */
 
 #ifdef SUPPORT_UNICODE
-if (utf &&
-#ifdef SUPPORT_JIT
-    !jit_checked_utf &&
-#endif
-    ((options & PCRE2_NO_UTF_CHECK) == 0 || allow_invalid))
+if (utf && ((options & PCRE2_NO_UTF_CHECK) == 0 || allow_invalid))
   {
 #if PCRE2_CODE_UNIT_WIDTH != 32
   BOOL skipped_bad_start = FALSE;
index b979a63470544bd67200452cc21e484157abe4ba..c396e8e88a7ccfe680195601448f7401ecc5b2eb 100644 (file)
 /(...)-(...)/jitfast
     abc-xyz\=get=2
 
+# Commented-out test; please re-enable and run manually on Unicode builds
+# #if unicode
+#
+# /\b/B,utf,ucp,jit=1
+#     \xff\x00\x00\=offset=2,ps
+#
+# #endif
+
 # End of testinput17
index 2f1c4e98fd8cf7bbf41a75f1d77c59aac0d088d3..e7334e436d93ac3e55f262375b29aab28d5100aa 100644 (file)
@@ -575,4 +575,12 @@ Failed: error -47: match limit exceeded
  2: xyz
  2G xyz (3)
 
+# Commented-out test; please re-enable and run manually on Unicode builds
+# #if unicode
+#
+# /\b/B,utf,ucp,jit=1
+#     \xff\x00\x00\=offset=2,ps
+#
+# #endif
+
 # End of testinput17